package com.hsogoo.ultraman.spring.boot;

import java.util.List;

import com.hsogoo.ultraman.listener.AutoRefreshConfigChangeListener;
import com.hsogoo.ultraman.spring.ConfigPropertySource;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;

import com.google.common.base.Splitter;
import com.hsogoo.ultraman.Config;
import com.hsogoo.ultraman.ConfigService;
import com.hsogoo.ultraman.constants.PropertySourceConstants;
import com.hsogoo.ultraman.container.ConfigContainer;
import com.hsogoo.ultraman.spring.ConfigPropertySourceFactory;

import lombok.extern.slf4j.Slf4j;

/**
 * Created by za-huangsaigang on 2018/9/20.
 */
@Slf4j
public class UltramanApplicationContextInitializer implements ApplicationContextInitializer {

    private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults();
    private final ConfigPropertySourceFactory configPropertySourceFactory = ConfigContainer.getBean(ConfigPropertySourceFactory.class);

    @Override
    public void initialize(ConfigurableApplicationContext context) {
        log.info("UltramanApplicationContextInitializer.initialize()...");
        initializePropertySources(context);
        initializePropertySourcesAutoRefresh(context);
    }

    private void initializePropertySources(ConfigurableApplicationContext context) {
        ConfigurableEnvironment environment = context.getEnvironment();
        if (environment.getPropertySources().contains(PropertySourceConstants.ULTRAMAN_CONFIG_BOOTSTRAP_NAME)) {
            //already initialized
            return;
        }
        List<String> namespaces = NAMESPACE_SPLITTER.splitToList(PropertySourceConstants.ULTRAMAN_DEFAULT_NAMESPACES);

        CompositePropertySource composite = new CompositePropertySource(PropertySourceConstants.ULTRAMAN_CONFIG_BOOTSTRAP_NAME);
        for (String namespace : namespaces) {
            Config config = ConfigService.getConfig(namespace);
            composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config));
        }

        environment.getPropertySources().addFirst(composite);
    }

    private void initializePropertySourcesAutoRefresh(ConfigurableApplicationContext context) {
        ConfigurableEnvironment environment = context.getEnvironment();

        AutoRefreshConfigChangeListener refreshConfigChangeListener = new AutoRefreshConfigChangeListener(
                environment, context);

        List<ConfigPropertySource> configPropertySources = configPropertySourceFactory.getAllConfigPropertySources();
        for (ConfigPropertySource configPropertySource : configPropertySources) {
            configPropertySource.addChangeListener(refreshConfigChangeListener);
        }
    }
}
